import os
import json
from py2neo import Graph, Node


class GoodsMap:
    def __init__(self):
        cur_dir = '/'.join(os.path.abspath(__file__).split('/')[:-1])
        self.data_path = os.path.join(cur_dir, 'data/goods_ekg.json')

        '''建立连接'''
        # self.g = Graph(
        #     host="127.0.0.1",  # neo4j 搭载服务器的ip地址，ifconfig可获取到
        #     http_port=7474,  # neo4j 服务器监听的端口号
        #     user="neo4j",  # 数据库user name，如果没有更改过，应该是neo4j
        #     password="gu13569740552")
        self.g = Graph('http://localhost:7474', user='neo4j', password='gu13569740552')

    '''读取文件'''

    def read_nodes(self):
        # 共6类实体节点
        goods = []  # 商品
        brands = []  # 品牌
        crowd = []  # 人群
        categories = []  # 商品类目
        themes = []  # 主题
        scenes = []  # 场景

        brand_sy = []  # 品牌同义词
        category_sy = []  # 类别同义词
        theme_sy = []  # 主题同义词
        scene_sy = []  # 场景同义词

        # 构建实体关系
        rels_brand = []  # 商品-品牌关系
        rels_crowd = []  # 商品-人群关系
        rels_category = []  # 商品-类目关系
        rels_theme = []  # 商品-主题关系
        rels_scene = []  # 商品-场景关系
        rels_include = []  # 商品类目-主题 / 主题-场景关系

        count = 0  # 记录数据条目数
        for data in open(self.data_path, encoding='utf8'):
            # 用字典记录同义词
            brand_dict = {}
            category_dict = {}
            theme_dict = {}
            scene_dict = {}

            count += 1
            print(count)
            # 读取json文件数据
            data_json = json.loads(data)
            # 将json对象转换为Python字典
            good = data_json['goods_name']
            goods.append(good)
            brand_dict['name'] = ''
            brand_dict['synonym'] = ''
            category_dict['name'] = ''
            category_dict['synonym'] = ''
            theme_dict['name'] = ''
            theme_dict['synonym'] = ''
            scene_dict['name'] = ''
            scene_dict['synonym'] = ''

            # 如果该条json记录中存在下述字段：记录字段、关系
            if 'crowd' in data_json:
                crowd += data_json['crowd']
                if data_json['crowd']:
                    for crow in data_json['crowd']:
                        rels_crowd.append([good, crow])

            if 'brand' in data_json:
                if data_json['brand']:
                    brands.append(data_json['brand'])
                    # 商品-品牌
                    rels_brand.append([good, data_json['brand']])
                    if 'brand_synonym' in data_json:
                        brand_dict['name'] = data_json['brand']
                        brand_dict['synonym'] = data_json['brand_synonym']
                    print(brand_dict)

            if 'category' in data_json:
                if data_json['category']:
                    categories.append(data_json['category'])
                    # 商品-类别
                    rels_category.append([good, data_json['category']])
                    category_dict['name'] = data_json['category']
                    if 'category_synonym' in data_json:
                        category_dict['synonym'] = data_json['category_synonym']
                    print(category_dict)

            if 'theme' in data_json:
                if data_json['theme']:
                    themes.append(data_json['theme'])
                    # 商品-主题
                    rels_theme.append([good, data_json['theme']])
                    theme_dict['name'] = data_json['theme']
                    if 'theme_synonym' in data_json:
                        theme_dict['synonym'] = data_json['theme_synonym']
                    print(theme_sy)

            if 'scene' in data_json:
                if data_json['scene']:
                    scenes.append(data_json['scene'])
                    # 商品-场景
                    rels_scene.append([good, data_json['scene']])
                    if 'scene_synonym' in data_json:
                        scene_dict['name'] = data_json['scene']
                        scene_dict['synonym'] = data_json['scene_synonym']
                    print(scene_dict)

            if brand_dict not in brand_sy:
                brand_sy.append(brand_dict)
            if category_dict not in category_sy:
                category_sy.append(category_dict)
            if theme_dict not in theme_sy:
                theme_sy.append(theme_dict)
            if scene_dict not in scene_sy:
                scene_sy.append(scene_dict)

        return set(goods), set(crowd), set(brands), set(categories), set(themes), set(scenes), brand_sy, category_sy, theme_sy, scene_sy, rels_brand, rels_crowd, rels_category, rels_theme, rels_scene, rels_include

    '''建立节点'''

    def create_node(self, label, nodes):
        count = 0  # 实体节点数
        for node_name in nodes:
            node = Node(label, name=node_name)
            self.g.create(node)
            count += 1
            print(count, len(nodes))
        return

    '''创建知识图谱带同义词属性的节点'''

    def create_node_sy(self, label, node_sy):
        count = 0
        for node_dict in node_sy:
            node = Node(label, name=node_dict['name'], synonym=node_dict['synonym'])
            self.g.create(node)
            count += 1
            print(count)
        return

    '''创建知识图谱实体节点类型schema'''

    def create_graphnodes(self):
        # return set(goods), set(crowd), set(brands), set(categories), set(themes), set(scenes), brand_sy,
        # category_sy, theme_sy, scene_sy, rels_brand, rels_crowd, rels_category, rels_theme, rels_scene, rels_include
        Goods, Crowd, Brands, Categories, Themes, Scenes, Brand_sy, Category_sy, Theme_sy, Scene_sy, rels_brand, rels_crowd, rels_category, rels_theme, rels_scene, rels_include = self.read_nodes()
        self.create_node('goods', Goods)
        print(len(Goods))
        self.create_node('crowd', Crowd)
        print(len(Crowd))
        self.create_node_sy('brand', Brand_sy)
        print(len(Brand_sy))
        self.create_node_sy('category', Category_sy)
        print(len(Category_sy))
        self.create_node_sy('theme', Theme_sy)
        print(len(Theme_sy))
        self.create_node_sy('scene', Scene_sy)
        print(len(Scene_sy))
        return

    '''创建实体关系边'''

    def create_graphrels(self):
        Goods, Crowd, Brands, Categories, Themes, Scenes, Brand_sy, Category_sy, Theme_sy, Scene_sy, rels_brand, rels_crowd, rels_category, rels_theme, rels_scene, rels_include = self.read_nodes()
        self.create_relationship('goods', 'brand', rels_brand, 'brand_to', '品牌')
        self.create_relationship('goods', 'crowd', rels_crowd, 'crowd_to', '人群')
        self.create_relationship('goods', 'category', rels_category, 'belong_to', '类别')
        self.create_relationship('goods', 'theme', rels_theme, 'aim_to', '主题')
        self.create_relationship('goods', 'scene', rels_scene, 'apply_to', '场景')
        self.create_relationship('category', 'theme', rels_include, 'include_in', '属于')
        self.create_relationship('theme', 'scene', rels_include, 'include_in', '属于')

    '''创建实体关联边'''

    def create_relationship(self, start_node, end_node, edges, rel_type, rel_name):
        count = 0
        # 去重处理
        set_edges = []
        for edge in edges:
            set_edges.append('###'.join(edge))
        all = len(set(set_edges))
        for edge in set(set_edges):
            edge = edge.split('###')
            p = edge[0]
            q = edge[1]
            # 创建关系
            query = "match(p:%s),(q:%s) where p.name='%s'and q.name='%s' create (p)-[rel:%s{name:'%s'}]->(q)" % (
                start_node, end_node, p, q, rel_type, rel_name)
            try:
                # 建立关系
                self.g.run(query)
                count += 1
                print(rel_type, count, all)
            except Exception as e:
                print(e)
        return

    '''导出数据'''

    def export_data(self):
        Goods, Crowd, Brands, Categories, Themes, Scenes, Brand_sy, Category_sy, Theme_sy, Scene_sy, rels_brand, rels_crowd, rels_category, rels_theme, rels_scene, rels_include = self.read_nodes()
        f_goods = open('./dict/goods.txt', 'w+', encoding='utf-8')
        f_brand = open('./dict/brand.txt', 'w+', encoding='utf-8')
        f_crowd = open('./dict/crowd.txt', 'w+', encoding='utf-8')
        f_category = open('./dict/category.txt', 'w+', encoding='utf-8')
        f_theme = open('./dict/theme.txt', 'w+', encoding='utf-8')
        f_scene = open('./dict/scene.txt', 'w+', encoding='utf-8')

        # 同义词也要写入
        f_goods.write('\n'.join(list(Goods)))
        f_brand.write('\n'.join(list(Brands)))
        for bsy in Brand_sy:
            for b in bsy['synonym']:
                f_brand.write('\n'+b)
        f_crowd.write('\n'.join(list(Crowd)))
        f_category.write('\n'.join(list(Categories)))
        for csy in Category_sy:
            for c in csy['synonym']:
                f_category.write('\n'+c)
        f_theme.write('\n'.join(list(Themes)))
        for tsy in Theme_sy:
            for t in tsy['synonym']:
                f_theme.write('\n'+t)
        f_scene.write('\n'.join(list(Scenes)))
        for ssy in Scene_sy:
            for s in ssy['synonym']:
                f_scene.write('\n'+s)

        f_goods.close()
        f_brand.close()
        f_crowd.close()
        f_category.close()
        f_theme.close()
        f_scene.close()
        return


if __name__ == '__main__':
    handler = GoodsMap()
    handler.create_graphnodes()
    handler.create_graphrels()
    handler.export_data()
